use std::collections::BinaryHeap;
use std::cmp::Reverse;

const NUM_TEST_VALUES: usize = 10000;

static mut test_array: [i32; NUM_TEST_VALUES] = [0; NUM_TEST_VALUES];

fn int_compare(a: &i32, b: &i32) -> std::cmp::Ordering {
    a.cmp(b)
}

fn test_binary_heap_new_free() {
    let _heap: BinaryHeap<i32> = BinaryHeap::new();
}

fn test_binary_heap_insert() {
    let mut heap: BinaryHeap<i32> = BinaryHeap::new();

    for i in 0..NUM_TEST_VALUES {
        unsafe {
            test_array[i] = i as i32;
            heap.push(test_array[i]);
        }
    }

    assert_eq!(heap.len(), NUM_TEST_VALUES);
}

fn test_min_heap() {
    let mut heap: BinaryHeap<i32> = BinaryHeap::new();

    for i in 0..NUM_TEST_VALUES {
        unsafe {
            test_array[i] = i as i32;
            heap.push(test_array[i]);
        }
    }

    let mut i = -1;
    while !heap.is_empty() {
        let val = heap.pop().unwrap();

        assert_eq!(val, i + 1);
        i = val;
    }

    assert!(heap.is_empty());
}

fn test_max_heap() {
    let mut heap: BinaryHeap<Reverse<i32>> = BinaryHeap::new();

    for i in 0..NUM_TEST_VALUES {
        unsafe {
            test_array[i] = i as i32;
            heap.push(Reverse(test_array[i]));
        }
    }

    let mut i = NUM_TEST_VALUES as i32;
    while !heap.is_empty() {
        let val = heap.pop().unwrap().0;

        assert_eq!(val, i - 1);
        i = val;
    }
}

fn test_out_of_memory() {
    // Out of memory scenario not applicable in Rust
}

fn main() {
    test_binary_heap_new_free();
    test_binary_heap_insert();
    test_min_heap();
    test_max_heap();
    test_out_of_memory();
}